
package com.groupbuying.settleconsumer.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.ons.api.SendResult;
import com.aliyun.openservices.ons.api.exception.ONSClientException;
import com.groupbuying.settleconsumer.connector.OrderFeign;
import com.groupbuying.settleconsumer.connector.StoreFeign;
import com.groupbuying.settleconsumer.connector.SysconfigFeign;
import com.groupbuying.settleconsumer.constants.*;
import com.groupbuying.settleconsumer.domain.*;
import com.groupbuying.settleconsumer.mq.SettleMQConfig;
import com.groupbuying.settleconsumer.service.*;
import com.groupbuying.settleconsumer.utils.JsonUtils;
import com.groupbuying.settleconsumer.utils.SettleParamsCheckUtils;
import com.groupbuying.settleconsumer.utils.apiresult.ApiResult;
import com.groupbuying.settleconsumer.utils.apiresult.ApiResultCode;
import com.groupbuying.settleconsumer.utils.apiresult.ObjectUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class OrderSettlementServiceImpl implements OrderSettlementService {

    public static final Logger logger = LoggerFactory.getLogger(OrderSettlementServiceImpl.class);

    @Autowired
    private SettleUshopSplitMaininfoService settleUshopSplitMaininfoService;

    @Autowired
    private SettleUshopSplitChannleService settleUshopSplitChannleService;

    @Autowired
    private SettleUshopSplitStoreService settleUshopSplitStoreService;

    @Autowired
    private SettleUshopSplitPlantformService settleUshopSplitPlantformService;

    @Autowired
    private SettleUshopSplitCurrencyService settleUshopSplitCurrencyService;

    @Autowired
    private SettleUshopSplitRluesService settleUshopSplitRluesService;

    @Autowired
    private SettleUshopFlowCurrencyService settleUshopFlowCurrencyService;

    @Autowired
    private SettleUshopFlowPlantformService settleUshopFlowPlantformService;

    @Autowired
    private SettleUshopFlowStoreService settleUshopFlowStoreService;

    @Autowired
    private Producer producer;

    @Autowired
    private SysconfigFeign sysconfigFeign;

    @Autowired
    private StoreFeign storeFeign;

    @Autowired
    private OrderFeign orderFeign;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult createOrederSettle(Map<String,Object> params){
        logger.error("OrderSettlementServiceImpl-->createOrederSettle params:"+ JSONUtils.toJSONString(params));
        String orderId = params.get("orderId").toString();
        int orderType =checkOrderType(orderId);
        if(OrderTypeEnumConstants.UNKNOW_CODE == orderType){
            logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId+" 未知订单类型，分账失败");
            return ApiResult.failure(ApiResultCode.FAILURE.code(),"未知订单类型，分账失败");
        }
        params.put("orderType",orderType);
        //参数校验
        boolean mainSettleFlag= SettleParamsCheckUtils.checkMainSettleParams(params);
        if(!mainSettleFlag){
            logger.error("OrderSettlementServiceImpl-->createOrederSettle fail reason: params is not qualified params:"+ JSONUtils.toJSONString(params));
            return ApiResult.failure("params is not qualified");
        }
        BigDecimal amount;
        String payType = (String) params.get("payType");
        if(OrderTypeEnumConstants.GYYD_CREDIT.equals(orderId.substring(4,7)) && PayInfoEnumConstants.ENUM_PAYTYPE_CUR.equals(payType)){
            logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId+" 订单为够样优店且为积分支付,金额取原订单金额"+params);
            //订单类型为够样优店且是积分支付
            Map<String,Object> orderInfo = orderFeign.orderInfo(orderId);
            logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId+" orderInfo result:::"+JsonUtils.objectToJson(orderInfo));
            amount = new BigDecimal(orderInfo.get("orderPrice")== null ? "0.00":Double.toString((Double) orderInfo.get("orderPrice")));
        }else{
            amount = ObjectUtils.getBigDecimal(params.get("totalAmount"));
        }
        params.put("amount",amount);
        try {
            //组装分账主表参数
            //查询商户中心获取门店ID和ruleId,业务员姓名，电话和商户通道费
            String counterId = (String) params.get("counterId");
            Map<String,Object> storeParams = new HashMap<>();
            storeParams.put("counterId",counterId);
            storeParams.put("delflag","1");
            logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId +" storeFeign.getMerchantsId params:::"+JsonUtils.objectToJson(storeParams));
            Map<String,Object> storeResult = storeFeign.getMerchantsId(storeParams);
            logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId +" storeFeign.getMerchantsId result:::"+JsonUtils.objectToJson(storeResult));
            String ruleId;
            String storeId;
            String ysUserState;
            if(MapUtils.isNotEmpty(storeResult)){
                ruleId= (String) storeResult.get("ruleId");
                storeId= (String) storeResult.get("storeId");
                ysUserState = (String) storeResult.get("ysUserState");//商户注册类型：1：为一清商户 其他为非一清
                params.put("ruleId",ruleId);
                params.put("storeId",storeId);
                params.put("ysUserCode",storeResult.get("ysUserCode"));
                params.put("operateMan",storeResult.get("operateMan"));
                params.put("operateTel",storeResult.get("operateTel"));
                params.put("storeRate",storeResult.get("storeRate"));
                params.put("storeSubsidyRate",storeResult.get("storeSubsidyRate"));
            }else{
                logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId +"  storeResult is null");
                return ApiResult.failure(ApiResultCode.FAILURE,"获取门店ID失败");
            }
            SettleUshopSplitMaininfoDO settleUshopSplitMaininfoDO = assembleMainSettleParams(params);
            params.put("settleRuleId",settleUshopSplitMaininfoDO.getSettleRules());
            //组装分账商户表、平台表、积分表、通道费表参数
            String payChannel = (String) params.get("payChannel");
            SettleUshopSplitRluesDO settleUshopSplitRluesDO = initializeRuleParams(params);
            if(settleUshopSplitMaininfoService.save(settleUshopSplitMaininfoDO)>0){
                logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId +" settleUshopSplitMaininfoDO save success");
                params.put("settleId",settleUshopSplitMaininfoDO.getSettleId());
                //生成分账规则
                if(settleUshopSplitRluesService.save(settleUshopSplitRluesDO)>0){
                    logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId +" settleSplitRlues save success");
                    params.put("settleSplitRluesDO",settleUshopSplitRluesDO);
                    //分账附表生成数据
                    Map<String,Object> separateParams = assembleSeparateSettleParams(params);
                    separateParams.put("orderId",orderId);
                    ApiResult settleResult = separateOrederSettle(separateParams);

                    //数据生成成功后发送mq消息
                    Map<String,Object> msgMap = (Map<String, Object>) settleResult.getResult();
                    params.put("currencyFlowAmount",msgMap.get("virtual_amount"));
                    params.put("plantformFlowAmount",msgMap.get("planform_amount"));
                    params.put("storeFlowAmount",msgMap.get("div_amount"));
                    params.put("orderId",orderId);
                    //生成流水信息
                    Map<String,Object> flowParams = initFlowInfo(params);
                    ApiResult flowResult = createSettlerFlow(flowParams);
                    if(ApiResultCode.SUCCESS.code().equals(settleResult.getCode()) &&
                            ApiResultCode.SUCCESS.code().equals(flowResult.getCode())){
                        msgMap.put("out_trade_no",params.get("outTradeNo"));
                        msgMap.put("total_amount",params.get("totalAmount"));
                        //发送MQ通知商户中心修改商户余额
                        Map<String,Object> storeMsg =  initToStoreInfoMSG(params);
                        logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId +" initToStoreInfoMSG result:::"+JsonUtils.objectToJson(storeMsg));
                        sendStoreMessage(storeMsg);
                        if(StoreEnumConstants.APPROVED.equals(ysUserState) && PayInfoEnumConstants.ENUM_PAYCHANNEL_YS.equals(payChannel)){
                            logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId +" 商户为一清商户,ysUserState:"+ysUserState);
                            //只有一清商户并且是支付渠道为银盛渠道才会发MQ消息通知调用银盛分账
                            sendSettleMessage(msgMap);
                        }
                        //发送MQ通知cheetah中心同步数据
                        Map<String,Object> cheetahMsg = new HashMap();
                        cheetahMsg.put("orderId",orderId);
                        cheetahMsg.put("tag",SettleMQConfig.ORDER_PAYMENT_INQUIRY_TAG);
                        sendCheetahMessage(cheetahMsg);
                        cheetahMsg.put("tag",SettleMQConfig.ORDER_STORE_MONEY_FLOW_TAG);
                        sendCheetahMessage(cheetahMsg);
                        cheetahMsg.put("tag",SettleMQConfig.TMP_ORDER_SETTLE_TAG);
                        sendCheetahMessage(cheetahMsg);
                        cheetahMsg.put("tag",SettleMQConfig.TMP_ORDER_PAY_TAG);
                        sendCheetahMessage(cheetahMsg);
                        cheetahMsg.put("tag",SettleMQConfig.TMP_ORDER_FLOW_TAG);
                        sendCheetahMessage(cheetahMsg);
                        return ApiResult.success();
                    }
                }
            }

        }catch (Exception e){
            logger.error("OrderSettlementServiceImpl-->createOrederSettle "+orderId +" fail e:",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return ApiResult.failure(ApiResultCode.FAILURE);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult separateOrederSettle(Map<String,Object> paramsMap){
        logger.error("OrderSettlementServiceImpl-->separateOrederSettle start params:::"+JsonUtils.objectToJson(paramsMap));
        String orderId = (String) paramsMap.get("orderId");
        SettleUshopSplitStoreDO settleUshopSplitStoreDO = (SettleUshopSplitStoreDO) paramsMap.get("settleUshopSplitStoreDO");
        SettleUshopSplitPlantformDO settleUshopSplitPlantformDO = (SettleUshopSplitPlantformDO) paramsMap.get("settleUshopSplitPlantformDO");
        SettleUshopSplitCurrencyDO settleUshopSplitCurrencyDO = (SettleUshopSplitCurrencyDO) paramsMap.get("settleUshopSplitCurrencyDO");
        SettleUshopSplitChannleDO settleUshopSplitChannleDO = (SettleUshopSplitChannleDO) paramsMap.get("settleUshopSplitChannleDO");
        //拼装回执信息
        Map<String,Object> resultMap = new HashMap<>();
        /*分账金额*/
        resultMap.put("div_amount",settleUshopSplitStoreDO.getAmount().setScale(2,BigDecimal.ROUND_HALF_DOWN));
        /*分账商户号*/
        resultMap.put("division_mer_usercode",paramsMap.get("ysUserCode"));
        /*积分金额*/
        resultMap.put("virtual_amount",settleUshopSplitCurrencyDO.getIntegral().setScale(2,BigDecimal.ROUND_HALF_DOWN));
        /*平台分账金额*/
        resultMap.put("planform_amount",settleUshopSplitPlantformDO.getAmount().setScale(2,BigDecimal.ROUND_HALF_DOWN));
        try{
            //生成商户分账单数据
            int merchantsCount = settleUshopSplitStoreService.save(settleUshopSplitStoreDO);
            logger.error("OrderSettlementServiceImpl-->separateOrederSettle "+orderId+" settleSplitMerchants save success!");
            //生成平台分账单数据
            int plantformCount = settleUshopSplitPlantformService.save(settleUshopSplitPlantformDO);
            logger.error("OrderSettlementServiceImpl-->separateOrederSettle "+orderId+" settleSplitPlantform save success!");
            //生成积分账单数据
            int virtualCount = settleUshopSplitCurrencyService.save(settleUshopSplitCurrencyDO);
            logger.error("OrderSettlementServiceImpl-->separateOrederSettle "+orderId+" settleSplitVirtual save success!");
            //生成通道费分账单数据
            int ChannleCount = settleUshopSplitChannleService.save(settleUshopSplitChannleDO);
            logger.error("OrderSettlementServiceImpl-->separateOrederSettle "+orderId+" settleSplitChannle save success!");

            logger.error("OrderSettlementServiceImpl-->separateOrederSettle "+orderId+" merchantsCount:"+merchantsCount
                    +",plantformCount:"+plantformCount+",virtualCount:"+virtualCount+",ChannleCount:"+ChannleCount);
            if(merchantsCount>0 && plantformCount>0 && virtualCount>0 && ChannleCount>0){
                logger.error("OrderSettlementServiceImpl-->separateOrederSettle "+orderId+" success");
                return  ApiResult.success(resultMap);
            }
        }catch (Exception e){
            logger.error("OrderSettlementServiceImpl-->separateOrederSettle "+orderId+" fail e:",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            ApiResult.failure();
        }
        logger.error("OrderSettlementServiceImpl-->separateOrederSettle "+orderId+" fail!");
        return ApiResult.failure();
    }

    private Map<String,Object> initToStoreInfoMSG(Map<String,Object> params){
        String orderId = params.get("orderId").toString();
        String payType = (String) params.get("payType");
        int orderType = (int) params.get("orderType");
        BigDecimal storeFlowAmount = (BigDecimal) params.get("storeFlowAmount");
        Object totalAmount = params.get("amount");
        String storeId = (String) params.get("storeId");
        //积分支付金额
        BigDecimal operIntegralAmount;
        //余额支付金额
        BigDecimal operBalanceAmount;
        //现金支付金额
        BigDecimal operCashAmount;
        String businessType;
        if(OrderTypeEnumConstants.GYYD_CODE == orderType){
            //够样优店
            businessType = SettleYsSplitReceiptEnumConstants.OPTIMAL_STORE_ORDER_SETTLE;
        }else{
            //优惠买单
            businessType = SettleYsSplitReceiptEnumConstants.ENUM_BUSINESS_SPLIT;
        }
        if(PayInfoEnumConstants.ENUM_PAYTYPE_BAL.equals(payType)){  //余额支付
            operBalanceAmount = storeFlowAmount;
            operIntegralAmount = new BigDecimal("0.00");
            operCashAmount = new BigDecimal("0.00");
        }else if(PayInfoEnumConstants.ENUM_PAYTYPE_CUR.equals(payType)){  //积分支付
            operIntegralAmount = storeFlowAmount;
            operBalanceAmount=  new BigDecimal("0.00");
            operCashAmount = new BigDecimal("0.00");
        }else{  //现金支付
            operCashAmount = storeFlowAmount;
            operBalanceAmount=  new BigDecimal("0.00");
            operIntegralAmount = new BigDecimal("0.00");
        }
        //发送MQ到商户中心添加对应金额
        Map<String,Object> messageMap = new ConcurrentHashMap<>();
        /*商户进账总金额*/
        messageMap.put("sum", storeFlowAmount);
        /*商户进账现金金额*/
        messageMap.put("operCashAmount",operCashAmount);
        /*商户进账余额金额*/
        messageMap.put("operBalanceAmount",operBalanceAmount);
        /*商户进账积分金额*/
        messageMap.put("operIntegralAmount",operIntegralAmount);
        /*支付单号*/
        messageMap.put("orderNo",orderId);
        /*商户账号*/
        messageMap.put("storeUuid",storeId);
        /*业务类型*/
        messageMap.put("businessType",businessType);
        /*金额标识--入账*/
        messageMap.put("inOrOut",SettleYsSplitReceiptEnumConstants.ENUM_IN_MONEY);
        /*商户会员号(待定--目前是商户号)*/
        messageMap.put("customerUuid",storeId);
        /*描述*/
        messageMap.put("description",String.format(StoreFlowDescription.SPLIT_SUCC,orderId,totalAmount.toString(),storeFlowAmount.toString()));
        logger.error("OrderSettlementServiceImpl-->initToStoreInfoMSG "+orderId+" result :::"+JsonUtils.objectToJson(messageMap));
        return messageMap;
    }

    private Map<String,Object> initFlowInfo(Map<String,Object> params){
        logger.error("OrderSettlementServiceImpl-->initFlowInfo params :::"+params);
        String orderId = (String) params.get("orderId");
        /*积分资金账户流水*/
        SettleUshopFlowCurrencyDO currencyFlowDO = new SettleUshopFlowCurrencyDO();
        currencyFlowDO.setId(sysconfigFeign.getFlowId());
        currencyFlowDO.setFlowType(SettleUshopFlowCurrencyEnumConstants.ENUM_FLOWTYPE_SPLIT);
        currencyFlowDO.setExternalId((String) params.get("settleId"));
        currencyFlowDO.setCustomerId((String) params.get(SettleUshopFlowCurrencySearchConstants.SEARCH_CUSTOMERID));
        currencyFlowDO.setAmount((BigDecimal) params.get("currencyFlowAmount"));
        currencyFlowDO.setNote("分账积分资金流水");
        currencyFlowDO.setIsDelete(SettleUshopFlowCurrencyEnumConstants.ENUM_ISDELETE_UNDEL);
        currencyFlowDO.setGmtCreate(new Date());

        /*平台资金账户流水*/
        SettleUshopFlowPlantformDO plantformFlowDO = new SettleUshopFlowPlantformDO();
        plantformFlowDO.setId(sysconfigFeign.getFlowId());
        plantformFlowDO.setExternalId((String) params.get("settleId"));
        plantformFlowDO.setFlowType(SettleUshopFlowPlantformEnumConstants.ENUM_FLOWTYPE_SPLIT);
        plantformFlowDO.setAmount((BigDecimal) params.get("plantformFlowAmount"));
        plantformFlowDO.setNote("分账平台资金流水");
        plantformFlowDO.setIsDelete(SettleUshopFlowPlantformEnumConstants.ENUM_ISDELETE_UNDEL);
        plantformFlowDO.setGmtCreate(new Date());

        /*商户资金流水*/
        SettleUshopFlowStoreDO storeFlowDO =new SettleUshopFlowStoreDO();
        storeFlowDO.setId(sysconfigFeign.getFlowId());
        storeFlowDO.setExternalId((String) params.get("settleId"));
        storeFlowDO.setFlowType(SettleUshopFlowStoreEnumConstants.ENUM_FLOWTYPE_SPLIT);
        storeFlowDO.setStoreId((String) params.get(SettleUshopFlowStoreSearchConstants.SEARCH_STOREID));
        storeFlowDO.setCheckstandId((String) params.get("counterId"));
        storeFlowDO.setAmount((BigDecimal) params.get("storeFlowAmount"));
        storeFlowDO.setNote("分账商户资金流水");
        storeFlowDO.setIsDelete(SettleUshopFlowStoreEnumConstants.ENUM_ISDELETE_UNDEL);
        storeFlowDO.setGmtCreate(new Date());
        storeFlowDO.setOperateMan((String) params.get("operateMan"));
        storeFlowDO.setOperateTel((String) params.get("operateTel"));

        Map<String,Object>resultMap = new HashMap();
        resultMap.put("currencyFlowDO",currencyFlowDO);
        resultMap.put("plantformFlowDO",plantformFlowDO);
        resultMap.put("storeFlowDO",storeFlowDO);
        resultMap.put("orderId",orderId);
        logger.error("OrderSettlementServiceImpl-->initFlowInfo "+orderId+" return :::"+resultMap);
        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    public ApiResult createSettlerFlow(Map<String,Object>params){
        logger.error("OrderSettlementServiceImpl-->createSettlerFlow params:::"+params);
        String orderId = (String) params.get("orderId");
        SettleUshopFlowCurrencyDO currencyFlowDO= (SettleUshopFlowCurrencyDO) params.get("currencyFlowDO");
        SettleUshopFlowPlantformDO plantformFlowDO = (SettleUshopFlowPlantformDO) params.get("plantformFlowDO");
        SettleUshopFlowStoreDO storeFlowDO = (SettleUshopFlowStoreDO) params.get("storeFlowDO");
        try{
            int currencyNum = settleUshopFlowCurrencyService.save(currencyFlowDO);
            logger.error("OrderSettlementServiceImpl-->createSettlerFlow "+orderId+" CurrencyFlow save success ");
            int plantformNum = settleUshopFlowPlantformService.save(plantformFlowDO);
            logger.error("OrderSettlementServiceImpl-->createSettlerFlow "+orderId+" PlantformFlow save success ");
            int storeNum = settleUshopFlowStoreService.save(storeFlowDO);
            logger.error("OrderSettlementServiceImpl-->createSettlerFlow "+orderId+" StoreFlow save success ");
            if(currencyNum>0 && plantformNum>0 && storeNum>0){
                logger.error("OrderSettlementServiceImpl-->createSettlerFlow "+orderId+" success currencyNum:"+currencyNum
                        +",plantformNum:"+plantformNum+",storeNum:"+storeNum);
                return ApiResult.success();
            }
        }catch(Exception e){
            logger.error("OrderSettlementServiceImpl-->createSettlerFlow "+orderId+" fail",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ApiResult.failure();
        }
        logger.error("OrderSettlementServiceImpl-->createSettlerFlow "+orderId+" save fail ");
        return ApiResult.failure();
    }

    //通知cheetah中心数据同步
    private void sendCheetahMessage(Map<String,Object> params){
        //初始化消息
        String msgBody = JsonUtils.objectToJson(params);
        String tag = (String) params.get("tag");
        String orderId = (String) params.get("orderId");
        Message msg = new Message(SettleMQConfig.CHEETAHTOPIC, tag, msgBody.getBytes());
        // 延时消息，单位毫秒（ms），在指定延迟时间（当前时间之后）进行投递，例如消息在 3 秒后投递
        long delayTime = System.currentTimeMillis() + 1000*60*1;
        msg.setStartDeliverTime(delayTime);
        logger.error(new Date() +"OrderSettlementServiceImpl-->sendCheetahMessage start! "+orderId+" type:"+tag+" params:::"+JsonUtils.objectToJson(params));
        try {
            if(StringUtils.isEmpty(tag)){
                logger.error(new Date() + "OrderSettlementServiceImpl-->sendCheetahMessage "+orderId+" Send message fail: msg is null");
                return;
            }
            SendResult sendResult = producer.send(msg);
            assert sendResult != null;
            logger.error(new Date() + "OrderSettlementServiceImpl-->sendCheetahMessage "+orderId+" Send message success! Topic is:"
                    + SettleMQConfig.CHEETAHTOPIC + " msgId is: " + sendResult.getMessageId());
        } catch (ONSClientException e) {
            // 消息发送失败，需要进行重试处理，可重新发送这条消息或持久化这条数据进行补偿处理
            logger.error(new Date() + "OrderSettlementServiceImpl-->sendCheetahMessage "+orderId+" Send mq message failed! Topic is:" + SettleMQConfig.CHEETAHTOPIC,e);
            e.printStackTrace();
        }
    }

    //通知分账中心开始调用银盛分账
    private void sendSettleMessage(Map<String,Object> params){
        //初始化消息
        String orderId = (String) params.get("orderId");
        String msgBody = JsonUtils.objectToJson(params);
        Message msg = new Message(SettleMQConfig.TOPIC, SettleMQConfig.YSSPLIT_TAG, msgBody.getBytes());
        logger.error(new Date() +"OrderSettlementServiceImpl-->sendSettleMessage start! params:::"+JsonUtils.objectToJson(params));

        try {
            SendResult sendResult = producer.send(msg);
            assert sendResult != null;
            logger.error(new Date() + "OrderSettlementServiceImpl-->sendSettleMessage "+orderId+" Send message success! Topic is:"
                    + SettleMQConfig.TOPIC + " msgId is: " + sendResult.getMessageId());
        } catch (ONSClientException e) {
            // 消息发送失败，需要进行重试处理，可重新发送这条消息或持久化这条数据进行补偿处理
            logger.error(new Date() + "OrderSettlementServiceImpl-->sendSettleMessage "+orderId+" Send mq message failed! Topic is:" + SettleMQConfig.TOPIC,e);
            e.printStackTrace();
        }
    }

    //分账完毕通知商户中心MQ
    private void sendStoreMessage(Map<String,Object> params){
        //初始化消息
        String orderId = (String) params.get("orderNo");
        String msgBody = JsonUtils.objectToJson(params);
        Message msg = new Message(SettleMQConfig.STORETOPIC, SettleMQConfig.NOTIFYSTORE_TAG, msgBody.getBytes());
        logger.error("OrderSettlementServiceImpl-->sendStoreMessage "+orderId+" start! params:::"+JsonUtils.objectToJson(params));
        try {
            SendResult sendResult = producer.send(msg);
            assert sendResult != null;
            logger.error("OrderSettlementServiceImpl-->sendStoreMessage "+orderId+" Send message success! Topic is:"
                    + SettleMQConfig.STORETOPIC + " msgId is: " + sendResult.getMessageId());
        } catch (ONSClientException e) {
            // 消息发送失败，需要进行重试处理，可重新发送这条消息或持久化这条数据进行补偿处理
            logger.error("OrderSettlementServiceImpl-->sendStoreMessage "+orderId+" Send mq message failed! Topic is:" + SettleMQConfig.TOPIC,e);
            e.printStackTrace();
        }
    }

    private SettleUshopSplitMaininfoDO  assembleMainSettleParams(Map<String,Object> params){
        String payType = (String) params.get("payType");
        int orderType = (int) params.get("orderType");
        BigDecimal amount;
        if(OrderTypeEnumConstants.GYYD_CODE == orderType && PayInfoEnumConstants.ENUM_PAYTYPE_CUR.equals(payType)){
            //只有积分支付金额用原订单金额
            amount = (BigDecimal) params.get("amount");
        }else{
            amount = new BigDecimal(params.get("totalAmount").toString());
        }
        SettleUshopSplitMaininfoDO maininfoDO =new SettleUshopSplitMaininfoDO();
        maininfoDO.setSettleId(sysconfigFeign.getSettleId());
        maininfoDO.setOrderId(params.get("orderId").toString());
        maininfoDO.setPayId(params.get("outTradeNo").toString());
        maininfoDO.setTotalAmount(amount);
        maininfoDO.setSettleRules(sysconfigFeign.getRuleId());
        maininfoDO.setSettleType(params.get("settleType").toString());
        maininfoDO.setPayChannel(params.get("payChannel").toString());
        maininfoDO.setIsDelete("1");
        maininfoDO.setStatus("0");//分账成功-SUC-0,分账失败-FALL-1
        maininfoDO.setGmtCreate(new Date());
        return maininfoDO;
    }

    private Map<String,Object> assembleSeparateSettleParams(Map<String,Object> params){
        logger.error("OrderSettlementServiceImpl-->assembleSeparateSettleParams params:::"+params);
        String orderId = (String) params.get("orderId");
        int orderType = (int) params.get("orderType");
        BigDecimal plantformFlowAmount;
        BigDecimal currencyFlowAmount;
        BigDecimal storeFlowAmount;
        String payType = (String) params.get("payType");
        BigDecimal amount;
        if(OrderTypeEnumConstants.GYYD_CODE == orderType && PayInfoEnumConstants.ENUM_PAYTYPE_CUR.equals(payType)){
            logger.error("OrderSettlementServiceImpl-->assembleSeparateSettleParams "+orderId+" 够样优店积分支付");
            amount = (BigDecimal) params.get("amount");
        }else{
            logger.error("OrderSettlementServiceImpl-->assembleSeparateSettleParams "+orderId+" 够样优店现金支付");
            amount = new BigDecimal(params.get("totalAmount").toString());
        }
        SettleUshopSplitRluesDO settleUshopSplitRluesDO = (SettleUshopSplitRluesDO) params.get("settleSplitRluesDO");

        BigDecimal customerRatio =  settleUshopSplitRluesDO.getCustomerRatio()== null? new BigDecimal(0):settleUshopSplitRluesDO.getCustomerRatio();
        BigDecimal plantformRatio = settleUshopSplitRluesDO.getPlatformRatio()== null? new BigDecimal(0):settleUshopSplitRluesDO.getPlatformRatio();
        BigDecimal virtualRatio = settleUshopSplitRluesDO.getVirtualRatio()== null? new BigDecimal(0):settleUshopSplitRluesDO.getVirtualRatio();
        BigDecimal channleRatio = settleUshopSplitRluesDO.getChannleRatio()== null? new BigDecimal(0):settleUshopSplitRluesDO.getChannleRatio();
        //生成商户分账表参数
        SettleUshopSplitStoreDO settleUshopSplitStoreDO = new SettleUshopSplitStoreDO();
        settleUshopSplitStoreDO.setSettleId(params.get("settleId").toString());
        settleUshopSplitStoreDO.setAmount(amount.multiply(customerRatio));
        storeFlowAmount  = amount.multiply(customerRatio);
        settleUshopSplitStoreDO.setCustomerId((String) params.get("storeId"));
        settleUshopSplitStoreDO.setIsDelete("1");
        settleUshopSplitStoreDO.setGmtCreate(new Date());

        //生成平台分账表参数
        SettleUshopSplitPlantformDO settleUshopSplitPlantformDO = new SettleUshopSplitPlantformDO();
        settleUshopSplitPlantformDO.setSettleId(params.get("settleId").toString());
        settleUshopSplitPlantformDO.setAmount(amount.multiply(plantformRatio));
        plantformFlowAmount = amount.multiply(plantformRatio);
        settleUshopSplitPlantformDO.setGmtCreate(new Date());
        settleUshopSplitPlantformDO.setIsDelete("1");

        //生成积分账户分账表参数
        SettleUshopSplitCurrencyDO settleUshopSplitCurrencyDO = new SettleUshopSplitCurrencyDO();
        settleUshopSplitCurrencyDO.setSettleId(params.get("settleId").toString());
        settleUshopSplitCurrencyDO.setIntegral(amount.multiply(virtualRatio));
        currencyFlowAmount = amount.multiply(virtualRatio);
        settleUshopSplitCurrencyDO.setIsDelete("1");
        settleUshopSplitCurrencyDO.setGmtCreate(new Date());

        //生成通道费分账表参数
        SettleUshopSplitChannleDO settleUshopSplitChannleDO = new SettleUshopSplitChannleDO();
        settleUshopSplitChannleDO.setSettleId(params.get("settleId").toString());
        settleUshopSplitChannleDO.setChannleAmount(amount.multiply(channleRatio));
        settleUshopSplitChannleDO.setIsDelete("1");
        settleUshopSplitChannleDO.setGmtCreate(new Date());

        Map<String,Object> result = new HashMap();
        result.put("ysUserCode",params.get("ysUserCode"));
        result.put("plantformFlowAmount",plantformFlowAmount);
        result.put("currencyFlowAmount",currencyFlowAmount);
        result.put("storeFlowAmount",storeFlowAmount);
        result.put("settleUshopSplitStoreDO",settleUshopSplitStoreDO);
        result.put("settleUshopSplitPlantformDO",settleUshopSplitPlantformDO);
        result.put("settleUshopSplitCurrencyDO",settleUshopSplitCurrencyDO);
        result.put("settleUshopSplitChannleDO",settleUshopSplitChannleDO);
        logger.error("OrderSettlementServiceImpl-->assembleSeparateSettleParams return :::"+result);
        return result;
    }

    private SettleUshopSplitRluesDO initializeRuleParams(Map<String,Object> params) throws Exception {
        String orderId = (String) params.get("orderId");//订单号
        String ruleId = (String) params.get("ruleId");
        String payType = (String) params.get("payType");//支付渠道
        int orderType = (int) params.get("orderType");//订单类型
        String storeId = (String) params.get("storeId");
        String settleRuleId = (String) params.get("settleRuleId");
        String payChannel = (String) params.get("payChannel");
        //商户的平台抽成费率
        String storeRate = (String) params.get("storeRate");
        String storeSubsidyRate = (String) params.get("storeSubsidyRate");
        //查询优惠规则表
        BigDecimal backCurrencyRatio ;//返积分比例
        BigDecimal platformRatio ;//平台抽成比例
        //根据支付渠道和支付类型，设置通道费和平台补贴费
        BigDecimal channleRatio ;//通道费费率
        BigDecimal subsidiesRatio ;//平台补贴费费率
        if(PayInfoEnumConstants.ENUM_PAYCHANNEL_OR.equals(payChannel)){
            channleRatio = new BigDecimal(SettleUshopSplitChannleEnumConstants.NATIVE_WX_RATIO);
            subsidiesRatio = new BigDecimal(SettleUshopSplitSubsidiesRatioEnumConstants.NATIVE_WX_RATIO);
        }else if (PayInfoEnumConstants.ENUM_PAYCHANNEL_SELF.equals(payChannel)){
            channleRatio = new BigDecimal("0.00");
            subsidiesRatio = new BigDecimal("0.00");
        }else{
            channleRatio = new BigDecimal(SettleUshopSplitChannleEnumConstants.YS_RATIO);
            subsidiesRatio = new BigDecimal(SettleUshopSplitSubsidiesRatioEnumConstants.YS_RATIO);
        }
        //商户结算比例
        BigDecimal customerRatio;
        try{
            if(OrderTypeEnumConstants.GYYD_CODE == orderType){
                //够样优店规则
                //通过查询sysConfig中心的优惠规则表和商户抽成规则表生成分账规则表
                Map<String,Object> ruleParam = new HashMap<>();
                ruleParam.put("ruleId",ruleId);
                // 抽成规则表
                logger.error("OrderSettlementServiceImpl.initializeRuleParams-->getOpexRule "+orderId+" params:::"+JsonUtils.objectToJson(ruleParam));
                Map<String,Object> opexRule = sysconfigFeign.getOpexRule(ruleParam);
                logger.error("OrderSettlementServiceImpl.initializeRuleParams-->getOpexRule "+orderId+" result:::"+JsonUtils.objectToJson(opexRule));
                double currencyExtracting = opexRule.get("currencyExtracting") == null ? 0.00 : (double) opexRule.get("currencyExtracting");
                double onlineExtracting = opexRule.get("onlineExtracting") == null ? 0.00 : (double) opexRule.get("onlineExtracting");
                double storeSettlement =  opexRule.get("storeSettlement") == null ? 0.00 : (double) opexRule.get("storeSettlement");
                double opexRuleBackCurrencyRatio =  opexRule.get("backCurrencyRatio") == null ? 0.00 : (double) opexRule.get("backCurrencyRatio");
                if(PayInfoEnumConstants.ENUM_PAYTYPE_CUR.equals(payType)){//积分支付
                    logger.error("OrderSettlementServiceImpl.initializeRuleParams 积分支付");
                    platformRatio = new BigDecimal(currencyExtracting).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_UP);
                    backCurrencyRatio = new BigDecimal("0.00");
                }else{//线上支付
                    logger.error("OrderSettlementServiceImpl.initializeRuleParams 线上支付");
                    platformRatio = new BigDecimal(onlineExtracting).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_UP);
                    backCurrencyRatio = new BigDecimal(opexRuleBackCurrencyRatio).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_UP);
                }
                customerRatio = new BigDecimal(storeSettlement).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_UP);
            }else{
                //优惠买单规则
                if(PayInfoEnumConstants.ENUM_PAYTYPE_BAL.equals(payType)){//余额支付
                    logger.error("OrderSettlementServiceImpl.initializeRuleParams "+orderId+" 优惠买单订单 余额支付 storeSubsidyRate:"+storeSubsidyRate);
                    platformRatio = StringUtils.isEmpty(storeSubsidyRate)? new BigDecimal("0.00"):new BigDecimal(storeSubsidyRate);
                    backCurrencyRatio = new BigDecimal("0.00");
                }else{
                    logger.error("OrderSettlementServiceImpl.initializeRuleParams "+orderId+" 优惠买单 storeRate:"+storeRate);
                    platformRatio = StringUtils.isEmpty(storeRate)? new BigDecimal("0.00"):new BigDecimal(storeRate);
                    backCurrencyRatio = new BigDecimal("0.00");
                }
                customerRatio = new BigDecimal("1.00").subtract(platformRatio.add(backCurrencyRatio).add(channleRatio)).add(subsidiesRatio);
            }
        }catch (Exception e){
            logger.error("OrderSettlementServiceImpl-->initializeRuleParams "+orderId+" sysconfigFeign fail",e);
            throw new Exception("sysconfigFeign fail");
        }
        //分账规则表中ruleId与优惠规则表和抽成规则表没有关系，会自己生成ruleId,并与分账主表做关联
        SettleUshopSplitRluesDO settleUshopSplitRluesDO = new SettleUshopSplitRluesDO();
        settleUshopSplitRluesDO.setCustomerId(storeId);
        settleUshopSplitRluesDO.setRluesId(settleRuleId);
        settleUshopSplitRluesDO.setVirtualRatio(backCurrencyRatio);
        settleUshopSplitRluesDO.setPlatformRatio(platformRatio);

        settleUshopSplitRluesDO.setChannleRatio(channleRatio);
        settleUshopSplitRluesDO.setSubsidiesRatio(subsidiesRatio);

        settleUshopSplitRluesDO.setCustomerRatio(customerRatio);
        settleUshopSplitRluesDO.setIsDelete("1");
        settleUshopSplitRluesDO.setGmtCreate(new Date());
        logger.error("OrderSettlementServiceImpl-->initializeRuleParams return SettleSplitRluesDO:"+settleUshopSplitRluesDO);
        return settleUshopSplitRluesDO;
    }

    private int checkOrderType(String orderId){
        String orderSub = orderId.substring(4,7);
        //根据订单号的第四位到第六位的三位数区分订单类型，够样优店和优惠买单两种类型匹配不同类型分账规则
        //000、002--够样优店,001--优惠买单
        if(OrderTypeEnumConstants.GYYD_CREDIT.equals(orderSub)){
            return OrderTypeEnumConstants.GYYD_CODE;
        }else if(OrderTypeEnumConstants.GYYD_REDEMPTION.equals(orderSub)){
            return OrderTypeEnumConstants.GYYD_CODE;
        }else if(OrderTypeEnumConstants.YHMD.equals(orderSub)){
            return OrderTypeEnumConstants.YHMD_CODE;
        }
        return 0;
    }
}
